# -*- coding: utf-8 -*-
from __future__ import unicode_literals

import json
import os
from datetime import datetime, timedelta
import uuid
import pytz
from django.utils.decorators import method_decorator
from django.db.models import Count
from django.urls import reverse
from django.utils import timezone
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, get_object_or_404, redirect
from django.db import transaction
from django.views.generic import ListView
from django.core.serializers import serialize
from django.views.generic.detail import SingleObjectMixin
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response

from Persimmon import settings
from auser.models import User
from movie.models import Movie, Review
from django.db.models import Q
from django.views.decorators.cache import cache_page
from django.http.response import HttpResponse, HttpResponseRedirect, JsonResponse

from post.models import ReviewComment, ReviewPraise


# todo:session cookie
def upload_generation_dir(dirs_name):
	today = datetime.today()
	url_part = dirs_name + '/{year}/{month}/'.format(year=today.year, month=today.month)
	dir_name = os.path.join(dirs_name, str(today.year), str(today.month))
	print('**' * 10, os.path.join(settings.MEDIA_ROOT, dir_name))
	if not os.path.exists(os.path.join(settings.MEDIA_ROOT, dir_name)):
		os.makedirs(os.path.join(settings.MEDIA_ROOT, dir_name))
	return dir_name, url_part


def image_upload(img, dir_name):
	allow_suffix = ['jpg', 'png', 'jpeg', 'gif', 'bmp']
	img_suffix = img.name.split('.')[-1]
	if img_suffix not in allow_suffix:
		return {'error': 1, 'message': '文件格式不允许'}
	relative_path_file, url_part = upload_generation_dir(dir_name)
	path = os.path.join(settings.MEDIA_ROOT, relative_path_file)
	print('^' * 7, path)
	if not os.path.exists(path):
		os.makedirs(path)
	file_name = str(uuid.uuid1()) + "." + img_suffix
	path_file = os.path.join(path, file_name)
	file_url = settings.MEDIA_URL + url_part + file_name
	open(path_file, 'wb').write(img.file.read())
	return {'error': 0, 'data': [file_url]}


# review里的图片上传获取外链
def upload_img(request, dir_name):
	result = {"error": 1, "message": "上传出错"}
	img = request.FILES.get('imgFile', None)
	if img:
		result = image_upload(img, dir_name)
	return HttpResponse(json.dumps(result), content_type="application/json")


class ReviewDetail(SingleObjectMixin, ListView):
	template_name = 'post/review_detail.html'

	def get(self, request, *args, **kwargs):
		self.object = self.get_object(queryset=Review.objects.all())
		return super(ReviewDetail, self).get(request, *args, **kwargs)

	def get_context_data(self, **kwargs):
		context = super(ReviewDetail, self).get_context_data(**kwargs)
		context['review'] = self.object
		# re = Review.objects.get(pk=1)
		context['comments'] = self.object.reviewcomment_set.all()
		return context

	def get_queryset(self):
		pass


@login_required(login_url='auser:login')
def comment_verify(request):
	if request.method == "POST":
		review_id = request.POST.get("review-id", None)
		user_id = request.POST.get("user-id", None)
		content = request.POST.get("comment-content", None)
		parent_id = request.POST.get("parent-id", None)
		if review_id and user_id:
			review = get_object_or_404(Review, pk=review_id)
			user = get_object_or_404(User, pk=user_id)
			if parent_id:
				parent_comment = get_object_or_404(ReviewComment, pk=parent_id) if parent_id else None
				# movie_title = Movie.objects.values("title")
				# username = User.objects.values("username")
				r_com = ReviewComment.objects.create(review=review, user=user,
				                                     user_username=user.username,
				                                     content=content, timestamp=timezone.now(),
				                                     parent_comment=parent_comment)
				r_com.save()
				return HttpResponseRedirect(reverse('post:review_detail', args=(review_id,)))
			r_com = ReviewComment.objects.create(review=review, user=user,
			                                     user_username=user.username,
			                                     content=content, timestamp=timezone.now())
			r_com.save()
			return JsonResponse({"state": 'success'})
		else:
			return JsonResponse({'state': "fail"})
	else:
		return redirect('/', args=(1,))


@login_required(login_url='auser:login')
def praise_verify(request):
	if request.method == "POST":
		rid = request.POST.get("review-id", None)
		uid = request.POST.get("user-id", None)
		status = request.POST.get("status", None)
		if rid and uid:
			re = get_object_or_404(Review, pk=rid)
			uu = get_object_or_404(User, pk=uid)
			with transaction.atomic():  # 启动一个事务
				# 保证两张表数据操作一致性
				if status == "1":
					ReviewPraise.objects.update_or_create(review=re,
					                                      user=uu,
					                                      defaults={"status": False,
					                                                "timestamp": timezone.now()})
					re.score -= 1
					re.save(update_fields=['score'])  # 专门某个字段更新，不然所有字段都会当成参数传过去
				else:
					ReviewPraise.objects.update_or_create(review=re,
					                                      user=uu,
					                                      defaults={"status": True,
					                                                "timestamp": timezone.now()})
					re.score += 1
					re.save(update_fields=['score'])
				return JsonResponse({"message": "success"})
		else:
			return JsonResponse({'fail': 'fail'})
	else:
		return redirect('/', args=(1,))


@login_required(login_url='auser:login')
def post_view(request, mid):
	movie = get_object_or_404(Movie, pk=mid)
	if request.method == "POST":
		body = request.POST.get('body', None)
		title = request.POST.get('title', None)
		if body and title:
			review = Review(title=title, body=body,
			                movie=movie, user=request.user,
			                timestamp=timezone.now())
			review.save()
			return JsonResponse({'id': review.id})
	return render(request, 'post/post_review.html', {'movie': movie})


@method_decorator(cache_page(60*60),name='get')
class ReviewSquare(ListView):
	template_name = 'post/review_square.html'
	context_object_name = 'reviews'
	state = 0

	def get_queryset(self):
		queryset = Review.objects.annotate(comments_count=Count('reviewcomment')) \
			.order_by('-comments_count')
		if len(queryset) > 8:
			self.state = 1
			queryset = queryset[0:8]
		return queryset

	def get_context_data(self, **kwargs):
		context = super(ReviewSquare, self).get_context_data()
		info = {}
		context['info'] = info
		context['info']['state'] = self.state
		context['info']['pageNo'] = 1
		return context


def search(request):
	if request.method == 'GET':
		result = {}
		size = 0
		key_name = 'key_name'
		if key_name in request.GET:
			result[key_name] = request.GET.get(key_name)
			reviews = Review.objects.filter(Q(movie__title__contains=request.GET.get(key_name)) |
			                                Q(title__contains=request.GET.get(key_name)))
			if reviews:
				result['code'] = 200
				r_reviews, size = _slice_get(reviews,section=1)
				result['size'] = size
				result['data'] = r_reviews
				return JsonResponse({'result': result})
			else:
				result['code'] = 400
				result['size'] = 0
				return JsonResponse({'result': result})

def load_more(request):
	if request.method == "GET":
		result = {}
		d_num = 4
		pageNo = request.GET.get("pageNo", None)
		key_name = request.GET.get('key_name', None)
		if pageNo:
			reviews = Review.objects.annotate(comments_count=Count('reviewcomment'))
			if key_name:
				reviews = reviews.filter(Q(movie__title__contains=key_name) |
				                         Q(title__contains=key_name))
			try:
				if len(reviews) <= 0:
					result['code'] = 400
					return JsonResponse({'result': result})
				else:
					r_reviews = reviews[int(pageNo) * 4:int(pageNo) * 4 + d_num]
			except IndexError:
				result['code'] = 200
				result['size'] = len(reviews)
				result['pageList'] = serialize('json', reviews, use_natural_foreign_keys=True)
			else:
				result['code'] = 200
				result['pageList'] = serialize('json', r_reviews, use_natural_foreign_keys=True)
				result['size'] = len(r_reviews)
			finally:
				result['pageNo'] = pageNo
				return JsonResponse({'result': result}, safe=False)
		return JsonResponse({'result': result})


def _slice_get(datas, section=8,using=True):
	length = len(datas)
	try:
		datas = datas[:section]
	except IndexError:
		datas = serialize("json", datas, use_natural_foreign_keys=using)
	else:
		datas = serialize("json", datas, use_natural_foreign_keys=using)
	return datas, length


def index_chart(request):
	if request.method == "POST":
		year_start = request.GET.get('year_start', None)
		year_end = request.GET.get('year_end', None)
		sort_way = request.GET.get("sort_way", None)
		if year_end and year_start:
			to_datetime = lambda strtime: datetime.strptime(strtime, '%Y').replace(tzinfo=pytz.UTC)
			Y_movies = Movie.objects.filter(year__range=[to_datetime(year_start), to_datetime(year_end)])
			if sort_way == "1":
				print('1')
				Y_movies = Y_movies.annotate(comments_count=Count('comment')).order_by('comments_count')
			elif sort_way == "0":
				Y_movies = Y_movies.order_by('rating')

			try:
				Y_movies = Y_movies[:10]
			except IndexError:
				movies = serialize("json", Y_movies, )
			else:
				movies = serialize("json", Y_movies)
			print(movies[0])
			return HttpResponse(movies)
		else:
			return HttpResponse("暂无数据")
	else:
		days = timedelta(days=365)
		movies = Movie.objects.filter(year__range=[datetime.now().replace(tzinfo=pytz.UTC) - days,
		                                           datetime.now().replace(tzinfo=pytz.UTC)])
		return render(request, 'post/chart_index.html')
